#!/bin/bash
# Podman 容器管理脚本
# 作者：chatterzhao
# 版本：1.1.0
# 描述：简化 Podman 容器和卷管理的交互式脚本

# 严格模式：提高脚本健壮性
# -e: 遇到错误立即退出
# -u: 使用未定义变量时报错
# -o pipefail: 管道中任何命令失败则整个管道失败
set -euo pipefail

# 脚本版本
VERSION="1.1.0"

# 调试开关（可通过环境变量控制）
DEBUG=${DEBUG:-false}

# 调试日志函数：仅在 DEBUG 模式下输出
debug_log() {
    if [[ "$DEBUG" == "true" ]]; then
        echo "[DEBUG] $*" >&2
    fi
}

# 显示脚本帮助信息
show_help() {
    echo "Podman 容器管理脚本的版本 v$VERSION"
    echo "注意使用命令的路径"
    echo "使用方式: $0 [命令] [子命令]"
    echo "使用方式，如: ./podman.sh build 或 ./podman.sh clean all"
    echo
    echo "命令："
    echo "  build            构建项目镜像"
    echo "  run              交互式运行容器"
    echo "  start            后台启动容器"
    echo "  stop             停止容器"
    echo "  exec             进入正在运行的容器"
    echo "  volumes create   创建项目专用卷"
    echo "  volumes list     列出项目相关的卷"
    echo "  volumes remove   删除项目相关的卷"
    echo "  clean all        清理所有容器、镜像和卷"
    echo "  clean container  清理容器"
    echo "  clean image      清理镜像"
    echo "  clean volume     清理卷"
    echo "  list             列出所有 Podman 资源"
    echo
    echo "选项："
    echo "  -h, --help       显示帮助信息"
    echo "  -v, --version    显示脚本版本"
    echo
    echo "环境变量："
    echo "  DEBUG=true       启用调试日志"
}

# 检查 Podman 是否可用
check_podman_availability() {
    if ! command -v podman &> /dev/null; then
        echo "错误：未检测到 Podman，请先安装 Podman" >&2
        echo "macOS 安装方式 brew install podman，其他系统请参考官方文档" >&2
        exit 1
    fi
}

# 检查 Podman 版本兼容性
check_podman_version() {
    local min_version="3.0.0"
    local current_version=$(podman version --format '{{.Version}}')
    
    debug_log "当前 Podman 版本：$current_version"
    
    if [[ "$(printf '%s\n' "$min_version" "$current_version" | sort -V | head -n1)" != "$min_version" ]]; then
        echo "警告：当前 Podman 版本 ($current_version) 低于建议版本 ($min_version)" >&2
    fi
}

# 处理帮助和版本选项
case "${1:-}" in
  "-h"|"--help")
    show_help
    exit 0
    ;;
  "-v"|"--version")
    echo "v$VERSION"
    exit 0
    ;;
esac

# 执行前的预检
check_podman_availability
check_podman_version

# 使用当前目录名作为默认镜像名
default_image_name=$(basename "$PWD")
image_name=${image_name:-$default_image_name}

# 根据命令类型决定是否询问镜像名
prompt_image_name() {
    local default_name="$1"
    local prompt_message="${2:-请输入镜像名}"
    
    read -p "${prompt_message} (默认: ${default_name}): " user_input
    if [ -n "$user_input" ]; then
        echo "$user_input"
    else
        echo "$default_name"
    fi
}

# 创建项目专用卷
create_volumes() {
    debug_log "开始创建项目专用卷"
    
    # 使用容器名作为卷名前缀，清理非法字符
    local volume_prefix=$(echo "$container_name" | sed -E 's/[^a-zA-Z0-9]/_/g')

    local volumes=(
        "${volume_prefix}_nuget:/root/.nuget"
    )

    for vol in "${volumes[@]}"; do
        volume_name=$(echo "$vol" | cut -d: -f1)
        volume_path=$(echo "$vol" | cut -d: -f2)

        # 检查卷是否已存在，不存在则创建
        if ! podman volume exists "$volume_name"; then
            podman volume create "$volume_name"
            echo "创建卷: $volume_name (挂载点: $volume_path)"
        else
            echo "卷已存在: $volume_name"
        fi
    done

    echo "当前项目卷："
    podman volume ls | grep "${volume_prefix}"
}

# 启动并创建容器
run_container() {
    debug_log "开始运行容器"
    
    # 获取本地镜像列表，排除 <none> 镜像
    local_images=$(podman images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>")
    
    if [ -z "$local_images" ]; then
        echo "未找到本地镜像，请先构建"
        exit 1
    fi

    # 如果存在多个本地镜像，让用户选择
    image_count=$(echo "$local_images" | wc -l)
    if [ "$image_count" -gt 1 ]; then
        echo "找到多个本地镜像："
        echo "$local_images" | nl
        read -p "请选择要使用的镜像编号: " image_choice
        
        if [[ "$image_choice" =~ ^[0-9]+$ ]] && 
           [[ "$image_choice" -ge 1 ]] && 
           [[ "$image_choice" -le "$image_count" ]]; then
            image_name=$(echo "$local_images" | sed -n "${image_choice}p")
        else
            echo "无效的选择，使用第一个镜像"
            image_name=$(echo "$local_images" | head -n 1)
        fi
    else
        # 如果只有一个镜像，直接使用
        image_name="$local_images"
    fi

    # 生成默认容器名
    default_container_name="avalonia_dev_$(date +%Y%m%d_%H%M%S)"
    read -p "请输入容器名 (默认: $default_container_name): " user_container_name
    
    # 如果用户输入为空，使用默认名称；否则使用用户输入
    if [ -z "$user_container_name" ]; then
        container_name="$default_container_name"
    else
        container_name="$user_container_name"
    fi
    
    # 系统和 Podman 诊断
    echo "系统诊断信息:"
    echo "系统架构: $(uname -m)"
    echo "Podman 版本: $(podman version | grep Version: | head -n 1)"
    
    # 镜像诊断
    echo "目标镜像: $image_name"
    podman inspect "$image_name" | grep -E "Architecture|Os"
    
    # 确保项目卷已创建
    create_volumes

    # 使用清理后的容器名作为卷名前缀
    local volume_prefix=$(echo "$container_name" | sed -E 's/[^a-zA-Z0-9]/_/g')

    # 调试输出
    echo "调试信息："
    echo "容器名: $container_name"
    echo "镜像名: $image_name"
    echo "当前目录: $(pwd)"
    echo "卷前缀: $volume_prefix"

    # 运行长期运行的容器
    # 获取 Dockerfile 所在的根目录
    PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    echo "项目根目录: $PROJECT_ROOT"

    podman run -d \
        --name "$container_name" \
        -v "$PROJECT_ROOT":/workspaces/project \
        -v "${volume_prefix}_nuget":/root/.nuget \
        -w /workspaces/project \
        --entrypoint /bin/bash \
        "$image_name" \
        -c "tail -f /dev/null" || {
        echo "容器启动失败，详细错误信息如下："
        return 1
    }

    echo "容器 $container_name 已在后台运行"
    echo "可以使用 'podman exec -it $container_name /bin/bash' 进入容器"
}

# 删除项目专用卷
remove_volumes() {
    debug_log "开始删除项目专用卷"
    
    volumes=$(podman volume ls --filter name=${volume_prefix} -q)
    if [ -n "$volumes" ]; then
        echo "即将删除以下卷："
        podman volume ls | grep ${volume_prefix}
        
        read -p "确认删除这些卷？(yes/cancel): " confirm
        if [[ "$confirm" == "yes" ]]; then
            podman volume rm $(podman volume ls --filter name=${volume_prefix} -q)
        fi
    else
        echo "没有找到与项目相关的卷"
    fi
}

# 列出当前 Podman 资源
list_podman_all_resources() {
    # 获取资源列表
    local containers=($(podman ps -a --format "{{.Names}}"))
    local images=($(podman images --format "{{.Repository}}:{{.Tag}}"))
    local volumes=($(podman volume ls --format "{{.Name}}"))

    # 检查是否有资源
    if [ ${#containers[@]} -eq 0 ] && [ ${#images[@]} -eq 0 ] && [ ${#volumes[@]} -eq 0 ]; then
        echo "没有检测到任何 Podman 资源"
        return 0
    fi

    # 打印资源概览
    echo "当前 Podman 资源："
    [ ${#containers[@]} -gt 0 ] && echo "容器数量：${#containers[@]}"
    [ ${#images[@]} -gt 0 ] && echo "镜像数量：${#images[@]}"
    [ ${#volumes[@]} -gt 0 ] && echo "卷数量：${#volumes[@]}"

    # 详细列表
    if [ ${#containers[@]} -gt 0 ]; then
        echo -e "\n容器列表："
        podman ps -a --format "- {{.Names}} (状态: {{.Status}}, 镜像: {{.Image}})"
    fi

    if [ ${#images[@]} -gt 0 ]; then
        echo -e "\n镜像列表："
        for image in "${images[@]}"; do
            # 排除 <none> 镜像
            if [[ "$image" != "<none>:<none>" ]]; then
                echo "- $image"
            fi
        done
    fi

    if [ ${#volumes[@]} -gt 0 ]; then
        echo -e "\n卷列表："
        for volume in "${volumes[@]}"; do
            echo "- $volume"
        done
    fi
}

# 容器清理
clean_containers() {
    # 获取容器列表
    local containers=()
    local container_count=0
    
    # 使用 podman ps -a 获取所有容器
    while IFS= read -r container; do
        containers+=("$container")
        ((container_count++))
    done < <(podman ps -a --format "{{.Names}}")
    
    # 如果没有容器
    if [ $container_count -eq 0 ]; then
        echo "没有找到任何容器"
        return 1
    fi

    # 显示容器列表
    echo -e "\n容器列表："
    for i in "${!containers[@]}"; do
        # 获取容器状态和镜像
        container_status=$(podman inspect "${containers[i]}" --format "{{.State.Status}}" 2>/dev/null)
        container_image=$(podman inspect "${containers[i]}" --format "{{.Image}}" 2>/dev/null)
        echo "$((i+1)). ${containers[i]} (状态: $container_status, 镜像: $container_image)"
    done
        
    read -p "选择操作 (all/序号/cancel): " container_choice
        
    if [[ "$container_choice" == "all" ]]; then
        for container in "${containers[@]}"; do
            echo "尝试删除容器：$container"
            podman stop "$container" || true
            podman rm "$container" || true
        done
    elif [[ "$container_choice" =~ ^[0-9]+$ ]] && 
         [[ "$container_choice" -ge 1 ]] && 
         [[ "$container_choice" -le ${#containers[@]} ]]; then
        container=${containers[$((container_choice-1))]}
        echo "尝试删除容器：$container"
        podman stop "$container" || true
        podman rm "$container" || true
    elif [[ "$container_choice" == "cancel" ]]; then
        echo "取消清理"
        return
    else
        echo "无效的选择"
    fi
}

# 镜像清理
clean_images() {
    # 获取镜像列表，包括悬空镜像
    local images=()  # 确保总是初始化
    local image_count=0
    local dangling_images=()
    
    # 获取非悬空镜像
    while IFS= read -r image; do
        if [[ -n "$image" ]] && [[ "$image" != "<none>:<none>" ]]; then
            images+=("$image")
            ((image_count++))
        fi
    done < <(podman images --format "{{.Repository}}:{{.Tag}}")
    
    # 获取悬空镜像
    while IFS= read -r dangling_image; do
        if [[ -n "$dangling_image" ]]; then
            dangling_images+=("$dangling_image")
        fi
    done < <(podman images -f "dangling=true" --format "{{.ID}}")

    # 如果没有镜像
    if [ ${#images[@]} -eq 0 ] && [ ${#dangling_images[@]} -eq 0 ]; then
        echo "没有找到可清理的镜像"
        return 1
    fi

    # 显示非悬空镜像列表
    if [ ${#images[@]} -gt 0 ]; then
        echo -e "\n镜像列表："
        for i in "${!images[@]}"; do
            image_id=$(podman inspect "${images[i]}" --format "{{.Id}}" 2>/dev/null)
            image_size=$(podman inspect "${images[i]}" --format "{{.Size}}" 2>/dev/null)
            echo "$((i+1)). ${images[i]} (ID: ${image_id:0:12}, 大小: $image_size)"
        done
    fi

    # 显示悬空镜像列表
    if [ ${#dangling_images[@]} -gt 0 ]; then
        echo -e "\n悬空镜像列表："
        for i in "${!dangling_images[@]}"; do
            echo "$((image_count + i + 1)). 悬空镜像 (ID: ${dangling_images[i]:0:12})"
        done
    fi
        
    read -p "选择操作 (all/序号/cancel/dangling): " image_choice
        
    if [[ "$image_choice" == "all" ]]; then
        # 先删除非悬空镜像（如果有）
        if [ ${#images[@]} -gt 0 ]; then
            for image in "${images[@]}"; do
                echo "尝试删除镜像：$image"
                podman rmi "$image" || true
            done
        fi
        # 再删除悬空镜像
        if [ ${#dangling_images[@]} -gt 0 ]; then
            for image in "${dangling_images[@]}"; do
                echo "尝试删除悬空镜像：$image"
                podman rmi "$image" || true
            done
        fi
    elif [[ "$image_choice" == "dangling" ]]; then
        # 专门删除悬空镜像
        if [ ${#dangling_images[@]} -gt 0 ]; then
            for image in "${dangling_images[@]}"; do
                echo "尝试删除悬空镜像：$image"
                podman rmi "$image" || true
            done
        fi
    elif [[ "$image_choice" =~ ^[0-9]+$ ]] && 
         [[ "$image_choice" -ge 1 ]] && 
         [[ "$image_choice" -le $((image_count + ${#dangling_images[@]})) ]]; then
        if [[ "$image_choice" -le $image_count ]]; then
            image=${images[$((image_choice-1))]}
            echo "尝试删除镜像：$image"
            podman rmi "$image" || true
        else
            image=${dangling_images[$((image_choice-image_count-1))]}
            echo "尝试删除悬空镜像：$image"
            podman rmi "$image" || true
        fi
    elif [[ "$image_choice" == "cancel" ]]; then
        echo "取消清理"
        return
    else
        echo "无效的选择"
    fi
}

# 卷清理
clean_volumes() {
    # 获取卷列表
    local volumes=()
    local volume_count=0
    
    # 使用 podman volume ls 获取所有卷
    while IFS= read -r volume; do
        volumes+=("$volume")
        ((volume_count++))
    done < <(podman volume ls --format "{{.Name}}")
    
    # 如果没有卷
    if [ $volume_count -eq 0 ]; then
        echo "没有找到可清理的卷"
        return 1
    fi

    # 显示卷列表
    echo -e "\n卷列表："
    for i in "${!volumes[@]}"; do
        # 获取卷详细信息
        volume_driver=$(podman volume inspect "${volumes[i]}" --format "{{.Driver}}" 2>/dev/null)
        volume_mountpoint=$(podman volume inspect "${volumes[i]}" --format "{{.Mountpoint}}" 2>/dev/null)
        echo "$((i+1)). ${volumes[i]} (驱动: $volume_driver, 挂载点: $volume_mountpoint)"
    done
        
    read -p "选择操作 (all/序号/cancel): " volume_choice
        
    if [[ "$volume_choice" == "all" ]]; then
        for volume in "${volumes[@]}"; do
            echo "尝试删除卷：$volume"
            podman volume rm "$volume" || true
        done
    elif [[ "$volume_choice" =~ ^[0-9]+$ ]] && 
         [[ "$volume_choice" -ge 1 ]] && 
         [[ "$volume_choice" -le ${#volumes[@]} ]]; then
        volume=${volumes[$((volume_choice-1))]}
        echo "尝试删除卷：$volume"
        podman volume rm "$volume" || true
    elif [[ "$volume_choice" == "cancel" ]]; then
        echo "取消清理"
        return
    else
        echo "无效的选择"
    fi
}

# 资源清理函数
clean_all_resources() {
    # 检查是否有资源需要清理
    list_podman_all_resources

    containers=($(podman ps -a --format "{{.Names}}"))
    images=($(podman images --format "{{.Repository}}:{{.Tag}}"))
    volumes=($(podman volume ls --format "{{.Name}}"))

    if [ ${#containers[@]} -eq 0 ] && [ ${#images[@]} -eq 0 ] && [ ${#volumes[@]} -eq 0 ]; then
        echo "没有可清理的资源"
        return 0
    fi

    # 全局清理确认
    read -p "是否确定清理所有资源？(yes/cancel): " confirm
    if [[ "$confirm" != "yes" ]]; then
        echo "清理操作已取消"
        return 1
    fi

    # 清理容器、镜像和卷
    clean_containers
    clean_images
    clean_volumes

    echo "清理完成"
}

# 构建镜像函数
build_image() {
    local dockerfiles=(
        "Dockerfile"
        "Dockerfile.avalonia"
        "Dockerfile.android"
        "Dockerfile.use-local-android"
        dockerfile.use-ubuntu-and-dotnet-sdk-and-android_sdk
    )
    
    local use_cache=true
    
    # 检查是否使用缓存
    for arg in "$@"; do
        if [ "$arg" = "--no-cache" ]; then
            use_cache=false
            break
        fi
    done
    
    echo "可用的 Dockerfile 列表："
    for i in "${!dockerfiles[@]}"; do
        echo "$((i+1)). ${dockerfiles[i]}"
    done
    echo "6. 构建所有镜像"
    echo "7. 取消"
    
    read -p "请选择要构建的镜像（输入序号）: " choice
    
    case $choice in
        1)
            build_single_image "${dockerfiles[0]}" "helloworld-base" "$use_cache"
            ;;
        2)
            build_single_image "${dockerfiles[1]}" "avalonia-img" "$use_cache"
            ;;
        3)
            build_single_image "${dockerfiles[2]}" "android-img" "$use_cache"
            ;;
        4)
            build_single_image "${dockerfiles[3]}" "use-local-android-img" "$use_cache"
            ;;
        5)
            build_single_image "${dockerfiles[4]}" "use-ubuntu-add-android-img" "$use_cache"
            ;;
        6)
            local success_count=0
            local failure_count=0
            
            for file in "${dockerfiles[@]}"; do
                if [ "$file" == "Dockerfile" ]; then
                    build_single_image "$file" "helloworld-base" "$use_cache" && ((success_count++)) || ((failure_count++))
                elif [ "$file" == "Dockerfile.avalonia" ]; then
                    build_single_image "$file" "avalonia-img" "$use_cache" && ((success_count++)) || ((failure_count++))
                elif [ "$file" == "Dockerfile.android" ]; then
                    build_single_image "$file" "android-img" "$use_cache" && ((success_count++)) || ((failure_count++))
                elif [ "$file" == "Dockerfile.use-local-android" ]; then
                    build_single_image "$file" "use-local-android-img" "$use_cache" && ((success_count++)) || ((failure_count++))
                elif [ "$file" == "dockerfile.use-ubuntu-and-dotnet-sdk-and-android_sdk" ]; then
                    build_single_image "$file" "use-ubuntu-add-android-img" "$use_cache" && ((success_count++)) || ((failure_count++))
                fi
            done
            
            echo "镜像构建完成：成功 $success_count 个，失败 $failure_count 个"
            ;;
        7)
            echo "已取消构建"
            return
            ;;
        *)
            echo "无效的选择，请重新输入"
            build_image "$@"
            ;;
    esac
}

# 新增辅助函数：构建单个镜像
build_single_image() {
    local dockerfile="$1"
    local image_name="$2"
    local use_cache="$3"
    
    echo "🏗️  正在构建镜像 ${image_name}..."
    
    if [ "$use_cache" = true ]; then
        podman build -t "$image_name" -f "$dockerfile" . && {
            echo "✅ 镜像 ${image_name} 构建成功"
            return 0
        } || {
            echo "❌ 镜像 ${image_name} 构建失败"
            return 1
        }
    else
        echo "🔄 禁用构建缓存"
        podman build --no-cache -t "$image_name" -f "$dockerfile" . && {
            echo "✅ 镜像 ${image_name} 构建成功"
            return 0
        } || {
            echo "❌ 镜像 ${image_name} 构建失败"
            return 1
        }
    fi
}

# 停止容器函数
stop_container() {
    debug_log "开始停止容器"

    # 获取当前运行的容器列表
    local running_containers=$(podman ps --format "{{.Names}}")

    if [ -z "$running_containers" ]; then
        echo "没有正在运行的容器"
        return 0
    fi

    # 如果只有一个容器，直接停止
    local container_count=$(echo "$running_containers" | wc -l)
    if [ "$container_count" -eq 1 ]; then
        local container_to_stop="$running_containers"
        podman stop "$container_to_stop"
        echo "已停止容器：$container_to_stop"
        return 0
    fi

    # 如果有多个容器，让用户选择
    echo "当前正在运行的容器："
    echo "$running_containers" | nl

    read -p "请选择要停止的容器编号: " container_choice

    if [[ "$container_choice" =~ ^[0-9]+$ ]] && 
       [[ "$container_choice" -ge 1 ]] && 
       [[ "$container_choice" -le "$container_count" ]]; then
        local container_to_stop=$(echo "$running_containers" | sed -n "${container_choice}p")
        podman stop "$container_to_stop"
        echo "已停止容器：$container_to_stop"
    else
        echo "无效的选择"
        return 1
    fi
}

# 交互式进入容器函数
exec_container() {
    debug_log "开始选择容器并执行"

    # 获取当前运行的容器列表
    local running_containers=$(podman ps --format "{{.Names}}")

    if [ -z "$running_containers" ]; then
        echo "没有正在运行的容器"
        return 0
    fi

    # 如果只有一个容器，直接进入
    local container_count=$(echo "$running_containers" | wc -l)
    if [ "$container_count" -eq 1 ]; then
        local container_to_exec="$running_containers"
        podman exec -it "$container_to_exec" /bin/bash
        return 0
    fi

    # 如果有多个容器，让用户选择
    echo "当前正在运行的容器："
    echo "$running_containers" | nl

    read -p "请选择要进入的容器编号: " container_choice

    if [[ "$container_choice" =~ ^[0-9]+$ ]] && 
       [[ "$container_choice" -ge 1 ]] && 
       [[ "$container_choice" -le "$container_count" ]]; then
        local container_to_exec=$(echo "$running_containers" | sed -n "${container_choice}p")
        podman exec -it "$container_to_exec" /bin/bash
    else
        echo "无效的选择"
        return 1
    fi
}

# 交互式启动容器函数
start_container() {
    debug_log "开始启动容器"

    # 获取当前所有容器列表
    local all_containers=$(podman ps -a --format "{{.Names}}")
    
    if [ -z "$all_containers" ]; then
        echo "未找到任何容器，请先创建容器"
        exit 1
    fi

    # 如果存在多个容器，让用户选择
    local container_count=$(echo "$all_containers" | wc -l)
    local selected_container=""
    
    if [ "$container_count" -gt 1 ]; then
        echo "找到多个容器："
        echo "$all_containers" | nl
        read -p "请选择要启动的容器编号: " container_choice
        
        if [[ "$container_choice" =~ ^[0-9]+$ ]] && 
           [[ "$container_choice" -ge 1 ]] && 
           [[ "$container_choice" -le "$container_count" ]]; then
            selected_container=$(echo "$all_containers" | sed -n "${container_choice}p")
        else
            echo "无效的选择，使用第一个容器"
            selected_container=$(echo "$all_containers" | head -n 1)
        fi
    else
        # 如果只有一个容器，直接使用
        selected_container="$all_containers"
    fi

    # 启动选定的容器
    podman start "$selected_container"
    
    # 显示容器详情
    podman ps
}

case "$1" in
  "build")
    build_image "$@"
    ;;
  "run")
    run_container
    ;;
  "start")
    start_container
    ;;
  "stop")
    stop_container
    ;;
  "exec")
    exec_container
    ;;
  "volumes")
    # 卷管理子命令
    case "$2" in
      "create")
        create_volumes
        ;;
      "remove")
        remove_volumes
        ;;
      "list")
        podman volume ls | grep ${volume_prefix}
        ;;
      *)
        echo "Usage: ./podman.sh volumes [create|remove|list]"
        ;;
    esac
    ;;
  "list")
    list_podman_all_resources
    ;;
  "clean")
    # 清理资源子命令
    case "$2" in
      "all")
        clean_all_resources
        ;;
      "container"|"containers")
        clean_containers
        ;;
      "image"|"images")
        clean_images
        ;;
      "volume"|"volumes")
        clean_volumes
        ;;
      *)
        echo "Usage: ./podman.sh clean [all|container|image|volume]"
        ;;
    esac
    ;;
  *)
    echo "Usage: ./podman.sh [build|run|start|stop|exec|volumes|clean|list]"
    ;;
esac
